﻿using Microsoft.Extensions.Caching.Memory;
using System;
using System.Collections.Generic;
using System.Reflection;

namespace Uiap.Infrastructure.Runtime.Caching.Memory
{
    /// <summary>
    /// 内存缓存
    /// </summary>
    public partial class MemoryCacheManager : ICacheManager
    {
        private readonly IMemoryCache _memoryCache;

        public MemoryCacheManager(IMemoryCache memoryCache)
        {
            _memoryCache = memoryCache;
        }

        /// <summary>
        /// 清除所有缓存
        /// </summary>
        public virtual void Clear()
        {
            IDictionary<object, object> cacheItems = AllItems();

            if (cacheItems == null) return;
            foreach (var cacheItem in cacheItems)
            {
                _memoryCache.Remove(cacheItem.Key);
            }
        }

        private IDictionary<object, object> AllItems()
        {
            const BindingFlags flags = BindingFlags.Instance | BindingFlags.NonPublic;
            var entries = _memoryCache.GetType().GetField("_entries", flags).GetValue(_memoryCache);
            var cacheItems = entries as IDictionary<object, object>;
            return cacheItems;
        }

        /// <summary>
        /// 获取或设置缓存
        /// </summary>
        /// <typeparam name="T">类型</typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public virtual T Get<T>(string key)
        {
            return _memoryCache.Get<T>(key);
        }

        /// <summary>
        /// 判断是否存在对应Key的缓存
        /// </summary>
        /// <param name="key">key</param>
        /// <returns></returns>
        public virtual bool IsSet(string key)
        {
            return AllItems().ContainsKey(key);
        }

        /// <summary>
        /// 移除Key对应的缓存对象
        /// </summary>
        /// <param name="key">key</param>
        public virtual void Remove(string key)
        {
            _memoryCache.Remove(key);
        }

        /// <summary>
        /// 根据匹配移除
        /// </summary>
        /// <param name="prefix">匹配表达式</param>
        public virtual void RemoveByPrefix(string prefix)
        {
            foreach (var item in AllItems())
            {
                if(item.Key.ToString().StartsWith(prefix))
                {
                    _memoryCache.Remove(item.Key);
                }
            }
        }

        /// <summary>
        /// 添加一个缓存对象
        /// </summary>
        /// <param name="key">key</param>
        /// <param name="data">缓存对象</param>
        /// <param name="cacheTime">缓存时间(s)</param>
        public virtual void Set(string key, object data, int cacheTime)
        {
            if (data == null)
                return;

            var timespan = DateTime.Now.AddSeconds(cacheTime) - DateTime.Now;
            _memoryCache.Set(key, data, timespan);
        }

        public virtual void Dispose()
        {

        }
    }
}
